#
#    Copyright (C) 2016 Francisco Javier Parra <franparpe@openmailbox.org>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
#

from PyQt5.QtWidgets import QTableWidget, QTableWidgetItem
from qtcam.tools.radius_of_curvature_checker import checkFlatFollowerRadius
from qtcam.tools.radius_of_curvature_checker import checkRollerFollowerRc
from qtcam.tools.angle_of_pressure_checker import checkPressureAngle


from PyQt5 import QtCore

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s


class Summary(QTableWidget):
    """This class is responsible for printing
a recopilation of the data

    """
    isContinuumMessage = "Continuum"
    isNotContinuumMessage = "Not continuum"
    
    def __init__(self, parent):
        super(Summary, self).__init__(parent)
        self.setHeaders()

    @classmethod
    def returnConinuityMessage(cls, isContinuum):
        """returns the corresponding message
        """
        if isContinuum:
            return cls.isContinuumMessage
        else:
            return cls.isNotContinuumMessage

    def setHeaders(self):
        """Initializes the headers
        """
        self.horHeaders = ["Maximum value",
                           "Minimum value",
                           "Comment"]
        self.vertHeaders = ["Displacement",
                            "Velocity",
                            "Acceleration",
                            "Jerk",
                            "Radius of curvature [mm]",
                            "Angle of pressure [º]"]
        self.setRowCount(len(self.vertHeaders))
        self.setColumnCount(len(self.horHeaders))
        self.setHorizontalHeaderLabels(self.horHeaders)
        self.setVerticalHeaderLabels(self.vertHeaders)
        self.horizontalHeader().setStretchLastSection(True)

    def setHeadersConjugateCam(self):
        """It sets the headers for the output of
        the cunjugate cam
        """
        self.horHeaders = ["Maximum value",
                           "Minimum value",
                           "Comment"]
        self.vertHeaders = ["Displacement",
                            "Velocity",
                            "Acceleration",
                            "Jerk",
                            "Radius of curvature of the original profile [mm]",
                            "Radius of curvature of the generated profile [mm]",
                            "Angle of pressure of the original profile [º]",
                            "Angle of pressure of the generated profile [º]"]
        self.setRowCount(len(self.vertHeaders))
        self.setColumnCount(len(self.horHeaders))
        self.setHorizontalHeaderLabels(self.horHeaders)
        self.setVerticalHeaderLabels(self.vertHeaders)
        self.horizontalHeader().setStretchLastSection(True)

    def populateCommonTable(self, theCam):
        """Populate the basic table
        """
        self.clear()
        maxDisplacement = round(theCam.maxDisplacement(), 3)
        minDisplacement = round(theCam.minDisplacement(), 3)
        maxVelocity = round(theCam.maxVelocity(), 3)
        minVelocity = round(theCam.minVelocity(), 3)
        maxAcceleration = round(theCam.maxAcceleration(), 3)
        minAcceleration = round(theCam.minAcceleration(), 3)
        maxJerk = round(theCam.maxJerk(), 3)
        minJerk = round(theCam.minJerk(), 3)
        
        maxDisplacement = QTableWidgetItem(str(maxDisplacement))
        minDisplacement = QTableWidgetItem(str(minDisplacement))
        maxVelocity = QTableWidgetItem(str(maxVelocity))
        minVelocity = QTableWidgetItem(str(minVelocity))
        maxAcceleration = QTableWidgetItem(str(maxAcceleration))
        minAcceleration = QTableWidgetItem(str(minAcceleration))
        maxJerk = QTableWidgetItem(str(maxJerk))
        minJerk = QTableWidgetItem(str(minJerk))

        # Place 
        self.setItem(0, 0, maxDisplacement)
        self.setItem(0, 1, minDisplacement)
        self.setItem(1, 0, maxVelocity)
        self.setItem(1, 1, minVelocity)
        self.setItem(2, 0, maxAcceleration)
        self.setItem(2, 1, minAcceleration)
        self.setItem(3, 0, maxJerk)
        self.setItem(3, 1, minJerk)

        # Is continuum?
        self._treatDisplacementContinuity(theCam.isDisplacementContinuum())
        self._treatVelocityContinuity(theCam.isVelocityContinuum())
        self._treatAccelerationContinuity(theCam.isAccelerationContinuum())
        self._treatJerkContinuity(theCam.isJerkContinuum())

    def populateCommonTableCW(self, theCam):
        """Populate the basic table
        """
        self.clear()
        maxDisplacement = round(theCam.maxDisplacement(), 3)
        minDisplacement = round(theCam.minDisplacement(), 3)
        maxVelocity = round(theCam.maxVelocity(), 3)
        minVelocity = round(theCam.minVelocity(), 3)
        maxAcceleration = round(theCam.maxAcceleration(), 3)
        minAcceleration = round(theCam.minAcceleration(), 3)
        maxJerk = round(theCam.maxJerk(), 3)
        minJerk = round(theCam.minJerk(), 3)
        
        maxDisplacement = QTableWidgetItem(str(maxDisplacement))
        minDisplacement = QTableWidgetItem(str(minDisplacement))
        maxVelocity = QTableWidgetItem(str(maxVelocity))
        minVelocity = QTableWidgetItem(str(minVelocity))
        maxAcceleration = QTableWidgetItem(str(maxAcceleration))
        minAcceleration = QTableWidgetItem(str(minAcceleration))
        maxJerk = QTableWidgetItem(str(maxJerk))
        minJerk = QTableWidgetItem(str(minJerk))

        # Place
        self.setItem(0, 0, maxDisplacement)
        self.setItem(0, 1, minDisplacement)
        self.setItem(1, 0, maxVelocity)
        self.setItem(1, 1, minVelocity)
        self.setItem(2, 0, maxAcceleration)
        self.setItem(2, 1, minAcceleration)
        self.setItem(3, 0, maxJerk)
        self.setItem(3, 1, minJerk)

        # Is continuum?
        self._treatDisplacementContinuity(theCam.isDisplacementContinuumCW())
        self._treatVelocityContinuity(theCam.isVelocityContinuumCW())
        self._treatAccelerationContinuity(theCam.isAccelerationContinuumCW())
        self._treatJerkContinuity(theCam.isJerkContinuumCW())

    def _treatDisplacementContinuity(self, isContinuum):
        """Operate with the coninuity
        """
        contMsg = QTableWidgetItem(self.returnConinuityMessage(isContinuum))
        self.setItem(0, 2, contMsg)

    def _treatVelocityContinuity(self, isContinuum):
        """Operate with the coninuity
        """
        contMsg = QTableWidgetItem(self.returnConinuityMessage(isContinuum))
        self.setItem(1, 2, contMsg)

    def _treatAccelerationContinuity(self, isContinuum):
        """Operate with the coninuity
        """
        contMsg = QTableWidgetItem(self.returnConinuityMessage(isContinuum))
        self.setItem(2, 2, contMsg)

    def _treatJerkContinuity(self, isContinuum):
        """Operate with the coninuity
        """
        contMsg = QTableWidgetItem(self.returnConinuityMessage(isContinuum))
        self.setItem(3, 2, contMsg)
        
    def populateMaxMinTable(self, theCam):
        """Papulate the first table with
        max and min values from the different laws
        """
        self.setHeaders()


        # Now for the radius of curvature and pressure angle
        maxCurvatureRadius = round(theCam.maxCurvatureRadius(), 3)
        minCurvatureRadius = round(theCam.minCurvatureRadius(), 3)
        maxPressureAngle = round(theCam.maxPressureAngle(), 3)
        minPressureAngle = round(theCam.minPressureAngle(), 3)

        maxCurvatureRadius = QTableWidgetItem(str(maxCurvatureRadius))
        minCurvatureRadius = QTableWidgetItem(str(minCurvatureRadius))
        maxPressureAngle = QTableWidgetItem(str(maxPressureAngle))
        minPressureAngle = QTableWidgetItem(str(minPressureAngle))

        self.setItem(4, 0, maxCurvatureRadius)
        self.setItem(4, 1, minCurvatureRadius)
        self.setItem(5, 0, maxPressureAngle)
        self.setItem(5, 1, minPressureAngle)

        radiusOfCurvatureList = theCam.curvatureRadiusList
        
        # Treat the curvRadius and the pressure angle comments
        if (theCam.followerType == 1) or (theCam.followerType == 4):
            self.radCorrect, messageC = checkFlatFollowerRadius(radiusOfCurvatureList)
        elif (theCam.followerType == 2) or (theCam.followerType == 5):
            # Roller
            radiusOfCurvaturePList = theCam.curvatureRadiusPList
            followerRadius = theCam.followerRadius
            self.radCorrect, messageC = checkRollerFollowerRc(radiusOfCurvatureList,
                                                              radiusOfCurvaturePList,
                                                              followerRadius)
        else:
            self.radCorrect, messageC = checkFlatFollowerRadius(radiusOfCurvatureList)

        # Treat the PressureAngle
        pAngleList = theCam.pressureAngleList
        self.pAngleCorrect, msgPA = checkPressureAngle(pAngleList)
        
        radiusOfCurvatureMSG = QTableWidgetItem(messageC)
        pressureAngleMSG = QTableWidgetItem(msgPA)
        self.setItem(4, 2, radiusOfCurvatureMSG)
        self.setItem(5, 2, pressureAngleMSG)

    def populateMaxMinTableConjugate(self, theCam):
        """Papulate the first table with
        max and min values from the different laws
        """
        self.setHeadersConjugateCam()
        # Now for the radius of curvature and pressure angle
        maxCurvatureRadius = QTableWidgetItem(str(theCam.maxCurvatureRadiusConjugate1()))
        minCurvatureRadius = QTableWidgetItem(str(theCam.minCurvatureRadiusConjugate1()))
        maxPressureAngle = QTableWidgetItem(str(theCam.maxPressureAngleConjugate1()))
        minPressureAngle = QTableWidgetItem(str(theCam.minPressureAngleConjugate1()))
        # Now for the radius of curvature and pressure angle of
        # the other profile
        maxCurvatureRadius2 = QTableWidgetItem(str(theCam.maxCurvatureRadiusConjugate2()))
        minCurvatureRadius2 = QTableWidgetItem(str(theCam.minCurvatureRadiusConjugate2()))
        maxPressureAngle2 = QTableWidgetItem(str(theCam.maxPressureAngleConjugate2()))
        minPressureAngle2 = QTableWidgetItem(str(theCam.minPressureAngleConjugate2()))
        self.setItem(4, 0, maxCurvatureRadius)
        self.setItem(4, 1, minCurvatureRadius)
        self.setItem(5, 0, maxCurvatureRadius2)
        self.setItem(5, 1, minCurvatureRadius2)
        self.setItem(6, 0, maxPressureAngle)
        self.setItem(6, 1, minPressureAngle)
        self.setItem(7, 0, maxPressureAngle2)
        self.setItem(7, 1, minPressureAngle2)

        # is continuum?
        self._treatDisplacementContinuity(theCam.isDisplacementContinuum())
        self._treatVelocityContinuity(theCam.isVelocityContinuum())
        self._treatAccelerationContinuity(theCam.isAccelerationContinuum())
        self._treatJerkContinuity(theCam.isJerkContinuum())

        radiusOfCurvtListUp = theCam.radiusOfCurvatureListUp
        radiusOfCurvtListLo = theCam.radiusOfCurvatureListLo

        # Treat the curvRadius and the pressure angle comments
        if (theCam.followerType == 0) or (theCam.followerType == 2):
            self.rad1Crct, messageC1 = checkFlatFollowerRadius(radiusOfCurvtListUp)
            self.rad2Crct, messageC2 = checkFlatFollowerRadius(radiusOfCurvtListLo)
        elif (theCam.followerType == 1) or (theCam.followerType == 3):
            # Roller
            radiusOfCurvtPListUp = theCam.radiusOfCurvaturePListUp
            radiusOfCurvtPListLo = theCam.radiusOfCurvaturePListLo
            followerRadius = theCam.followerRadius
            self.rad1Correct, messageC1 = checkRollerFollowerRc(radiusOfCurvtListUp,
                                                                radiusOfCurvtPListUp,
                                                                followerRadius)
            self.rad2Correct, messageC2 = checkRollerFollowerRc(radiusOfCurvtListLo,
                                                                radiusOfCurvtPListLo,
                                                                followerRadius)

        # Treat pressure angle
        pAngleListUp = theCam.pressureAngleListUp
        pAngleListLo = theCam.pressureAngleListLo
        self.pAngleCorrect1, msgPA1 = checkPressureAngle(pAngleListUp)
        self.pAngleCorrect2, msgPA2 = checkPressureAngle(pAngleListLo)

        radiusOfCurvatUpMSG = QTableWidgetItem(messageC1)
        radiusOfCurvatLoMSG = QTableWidgetItem(messageC2)
        pressureAngleUpMSG = QTableWidgetItem(msgPA1)
        pressureAngleLoMSG = QTableWidgetItem(msgPA2)

        self.setItem(4, 2, radiusOfCurvatUpMSG)
        self.setItem(5, 2, radiusOfCurvatLoMSG)
        self.setItem(6, 2, pressureAngleUpMSG)
        self.setItem(7, 2, pressureAngleLoMSG)

    def populateMaxMinTableConstWidth(self, theCam):
        """Papulate the first table with
        max and min values from the different laws
        """
        self.setHeaders()
        # Is continuum?
        self._treatDisplacementContinuity(theCam.isDisplacementContinuum())
        self._treatVelocityContinuity(theCam.isVelocityContinuum())
        self._treatAccelerationContinuity(theCam.isAccelerationContinuum())
        self._treatJerkContinuity(theCam.isJerkContinuum())

        # Now for the radius of curvature and pressure angle
        maxCurvatureRadius = round(theCam.maxCurvatureRadius(), 3)
        minCurvatureRadius = round(theCam.minCurvatureRadius(), 3)
        maxPressureAngle = round(theCam.maxPressureAngle(), 3)
        minPressureAngle = round(theCam.minPressureAngle(), 3)

        maxCurvatureRadius = QTableWidgetItem(str(maxCurvatureRadius))
        minCurvatureRadius = QTableWidgetItem(str(minCurvatureRadius))
        maxPressureAngle = QTableWidgetItem(str(maxPressureAngle))
        minPressureAngle = QTableWidgetItem(str(minPressureAngle))

        self.setItem(4, 0, maxCurvatureRadius)
        self.setItem(4, 1, minCurvatureRadius)
        self.setItem(5, 0, maxPressureAngle)
        self.setItem(5, 1, minPressureAngle)

        radiusOfCurvatureList = theCam.curvatureRadiusList
        
        # Treat the curvRadius and the pressure angle comments
        if (theCam.followerType == 1) or (theCam.followerType == 4):
            self.radCorrect, messageC = checkFlatFollowerRadius(radiusOfCurvatureList)
        elif (theCam.followerType == 2) or (theCam.followerType == 5):
            # Roller
            radiusOfCurvaturePList = theCam.curvatureRadiusPList
            followerRadius = theCam.followerRadius
            self.radCorrect, messageC = checkRollerFollowerRc(radiusOfCurvatureList,
                                                              radiusOfCurvaturePList,
                                                              followerRadius)

        # Treat the PressureAngle
        pAngleList = theCam.pressureAngleList
        self.pAngleCorrect, msgPA = checkPressureAngle(pAngleList)
        
        radiusOfCurvatureMSG = QTableWidgetItem(messageC)
        pressureAngleMSG = QTableWidgetItem(msgPA)
        self.setItem(4, 2, radiusOfCurvatureMSG)
        self.setItem(5, 2, pressureAngleMSG)

